import * as Koa from 'koa';
import { Transaction } from 'tiny-entity2';
import { Guid, route, RouteOptionsVerify, ServiceManager, UsingLock } from "../../common";
import { ServiceException } from '../../common/excpetion';
import { ApiDataContext } from '../../domain/apiDataContext';
import { Department } from '../../domain/models/department';
import { OrganizationTree } from '../../domain/models/organizationTree';
import { DepartmentService } from '../../service/DepartmentService';
import { OrganizationTreeService } from '../../service/organizationTreeService';
const departmentSvr = ServiceManager.Current.GetService<DepartmentService>('DepartmentService');
const orzTreeSvr = ServiceManager.Current.GetService<OrganizationTreeService>('OrganizationTreeService');

class DepartmentController {
    @route(new RouteOptionsVerify('GET', '/api/department'))
    async queryDepartments(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let params = ctx.query;
        params.organizationId=rootOrgId;
        
        let department = await departmentSvr.QueryDepartment(params);
        ctx.response.body = department;
        await next();
    }
    @route(new RouteOptionsVerify('GET', '/api/department/:id'))
    async getDepartmentInfoById(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let id = ctx.params.id;
        let data = await departmentSvr.GetDepartmentById(id);

        let orgtrees: OrganizationTree[] = await orzTreeSvr.QueryOrganizationTree({organizationId:rootOrgId,objectName:data.ClassName(), objectId: id });
        data.orgTree = <OrganizationTree>{};
        if (orgtrees && orgtrees.length > 0) {
            data.orgTree = orgtrees[0];
        }

        ctx.response.body = data;
        await next();
    }
    @route(new RouteOptionsVerify('POST', '/api/department'))
    async createDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let department:Department = ctx.request.body;
        department.orgTree.organizationId=rootOrgId;
        checkData(department);

        department.id = Guid.GetGuid();
        department.isDelete=false;
        department.createTime=Date.now();
        department.modifyTime=Date.now();

        let orgTree = new OrganizationTree();
        orgTree.id = Guid.GetGuid();
        orgTree.isDelete = false;

        if(rootOrgId)
        {
            orgTree.organizationId =rootOrgId;
        }

        await Transaction(new ApiDataContext(), async datactx => {
            let result = await departmentSvr.CreateDepartment(department,datactx);
            orgTree.objectId = result.id;
            orgTree.objectName = result.ClassName();
            orgTree.nodeName = result.name;
            orgTree.parentId= department.orgTree.parentId;

            result.orgTree = await orzTreeSvr.CreateorganizationTree(orgTree,datactx);
            ctx.response.body = result;
        });
        
        await next();
    }
    @route(new RouteOptionsVerify('PUT', '/api/department'))
    async updateDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let department = <Department>ctx.request.body;
        if (!department.id) {
            throw new ServiceException('id 不能为空！', 'not_be_null');
        }
        department.orgTree.organizationId=rootOrgId;
        department.modifyTime=Date.now();
        checkData(department);
        await UsingLock(department.id, async () => {
            await Transaction(new ApiDataContext(), async datactx => {
                let depData = await departmentSvr.GetDepartmentById(department.id);
                depData.ConverToEntity(department);
                let result = await departmentSvr.UpdateDepartment(depData,datactx);
                result.orgTree.nodeName=depData.name;
                result.orgTree = await orzTreeSvr.UpdateorganizationTree(department.orgTree, datactx);
                ctx.response.body = result;
            });
        })

        await next();
    }
    @route(new RouteOptionsVerify('DELETE', '/api/department/:id'))
    async deleteDepartment(ctx: Koa.Context, next) {
        let rootOrgId = ctx.headers['orgid'];
        let id = ctx.params.id;
        if (!id) {
            throw new ServiceException('id 不能为空！', 'not_be_null');
        }
        let department = await departmentSvr.GetDepartmentById(id);
        department.isDelete = true;

        ctx.response.body =await UsingLock(department.id, async () => {
            return await Transaction(new ApiDataContext(), async datactx => {
                let result = departmentSvr.UpdateDepartment(department,datactx);
                let deptrees = await orzTreeSvr.QueryOrganizationTree({ objectId: department.id,organizationId:rootOrgId});

                if (deptrees && deptrees.length > 0) {
                    department.orgTree = deptrees[0];
                    department.orgTree.isDelete = true;
                    await orzTreeSvr.UpdateorganizationTree(department.orgTree, datactx);
                }
                return result;
            })
        })
      
        await next();
    }
}

const checkData = (data: Department) => {
    if (!data.name) {
        throw new ServiceException('未填写部门名称！');
    }
    if (!data.organizationId) {
        throw new ServiceException('未传入所属组织编号！');
    }

    if (!data.orgTree.organizationId) {
        throw new ServiceException('未传入根组织编号！');
    }
}